package javasec.contempt.dialogs;

import java.io.ByteArrayOutputStream
;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

import java.rmi.RemoteException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

import javasec.contempt.data.SeedConnector;
import javasec.seed.DataSeedInterface;

import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;


public class KeyWindow extends ApplicationWindow
{
	String text="";
	
	Tree keyTree=null;
	
	TreeItem idItem=null;
	TreeItem friendsItem=null;
	TreeItem serversItem=null;
	
	public KeyStore idStore=null;
	public KeyStore friendsStore=null;
	public KeyStore serversStore=null;
	
	public static KeyWindow instance=null;
	
	public KeyWindow()
	{
		super(null);
		instance=this; // remember this key instance
		
		// load up the keystores
		try
		{
			idStore=KeyStore.getInstance(KeyStore.getDefaultType());
			friendsStore=KeyStore.getInstance(KeyStore.getDefaultType());
			serversStore=KeyStore.getInstance(KeyStore.getDefaultType());
			idStore.load(new FileInputStream(SeedConnector.idPath),SeedConnector.globalPass.toCharArray());
			friendsStore.load(new FileInputStream(SeedConnector.friendsPath),SeedConnector.globalPass.toCharArray());
			serversStore.load(new FileInputStream(SeedConnector.serversPath),SeedConnector.globalPass.toCharArray());
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}	
	}
	
	protected Control createContents(Composite parent)
	{
		parent.setSize(400,300);
		getShell().setText("key manager");
		keyTree=new Tree(parent,SWT.VIRTUAL|SWT.BORDER);

		// set up the three root TreeItems
		idItem=new TreeItem(keyTree,SWT.NONE);
		friendsItem=new TreeItem(keyTree,SWT.NONE);
		serversItem=new TreeItem(keyTree,SWT.NONE);
		friendsItem.setText("friends");
		idItem.setText("identities");
		serversItem.setText("servers");

		// populate the keystore items with names of the keys
		this.populate(idItem, idStore);
		this.populate(friendsItem, friendsStore);
		this.populate(serversItem, serversStore);

		// expand all the root tree items
		idItem.setExpanded(true);
		friendsItem.setExpanded(true);
		serversItem.setExpanded(true);
		
		// enable right clicking on keys
		createContextMenu(parent);
		
		// set the tree to expand when double clicked on (or enter)
		keyTree.addSelectionListener(new SelectionListener()
		{
			public void widgetDefaultSelected(SelectionEvent e)
			{
				if(e.item instanceof TreeItem)
				{
					TreeItem item=(TreeItem)e.item;
					item.setExpanded(!item.getExpanded());
				}
			}

			public void widgetSelected(SelectionEvent e)
			{
			}
		});

		
		return parent;
	}
	
	// populate the treeitem with the keys from the truststore
	public void populate(TreeItem treeItem, KeyStore trustStore)
	{
		try
		{
			Enumeration<String> aliasEnumeration=trustStore.aliases();
			while(aliasEnumeration.hasMoreElements())
			{
				String alias=aliasEnumeration.nextElement();
				String fingerprintString="";
				Certificate keyCertificate=trustStore.getCertificate(alias);
				if(keyCertificate instanceof X509Certificate)
				{
					for(byte b : MessageDigest.getInstance("SHA1").digest(keyCertificate.getEncoded()))
					{
						if(Integer.toString(b&0xFF,16).length()==1)fingerprintString+="0";
						fingerprintString+=(Integer.toString(b&0xFF,16)); // maybe force to hex?
					}
				}
				
				new TreeItem(treeItem,SWT.NONE).setText(alias+": "+fingerprintString);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public void createContextMenu(Composite parent)
	{
		Menu menu=new Menu(parent);
		
		MenuItem viewKey=new MenuItem(menu,SWT.PUSH);
		viewKey.setText("view public key");
		viewKey.addSelectionListener(new SelectionListener()
		{
			public void widgetDefaultSelected(SelectionEvent e)
			{
			}

			public void widgetSelected(SelectionEvent e)
			{
				String hexString="";
				
				try
				{
					System.out.println(e);
				
					TreeItem item=keyTree.getSelection()[0];
					if(item==null)return;
					TreeItem parent=item.getParentItem();
					if(parent==null)return;
					
					KeyStore store=null; // which keystore to look in?
					if(parent.getText().equals("identities"))store=idStore;
					if(parent.getText().equals("friends"))store=friendsStore;
					if(parent.getText().equals("servers"))store=serversStore;
					System.out.println(parent.getText());
					
					String alias=null; // alias of the certificate in the keystore
					alias=item.getText().split(":")[0]; // split the string at the colon
					System.out.println(alias);
					
					Certificate cert=store.getCertificate(alias);
					if(cert==null)return;
					
					ByteArrayOutputStream oStream=new ByteArrayOutputStream();
					ObjectOutputStream ooStream=new ObjectOutputStream(oStream);
					ooStream.writeObject(cert);

					byte[] array=oStream.toByteArray();
					
					for(byte b:array)
					{
						if(Integer.toString(b&0xFF,16).length()==1)hexString+="0";
						hexString+=(Integer.toString(b&0xFF,16)); // force to hex
					}
				}
				catch (Exception e1)
				{
					return;
				}
				
				TextWindow textWindow=new TextWindow(hexString);
				textWindow.open();
			}
		});
		
		MenuItem importKey=new MenuItem(menu,SWT.PUSH);
		importKey.setText("import key");
		importKey.addSelectionListener(new SelectionListener()
		{
			public void widgetDefaultSelected(SelectionEvent e)
			{	
			}
			public void widgetSelected(SelectionEvent e)
			{
				KeyImportDialog importDialog=new KeyImportDialog(null,"import key");
				importDialog.open();
				if(importDialog.aborted)return;
				if(importDialog.certificate==null)return;
				if(importDialog.alias==null)return;
				
				TreeItem item=keyTree.getSelection()[0];
				if(item==null)return;
				TreeItem parent=item.getParentItem();
				if(parent!=null)item=parent;
				
				KeyStore store=null; // which keystore to look in?
				if(item.getText().equals("identities"))store=idStore;
				if(item.getText().equals("friends"))store=friendsStore;
				if(item.getText().equals("servers"))store=serversStore;
				
				try
				{
					if(store.containsAlias(importDialog.alias))return;
					store.setCertificateEntry(importDialog.alias, importDialog.certificate);
					
					// calculate the fingerprint of the certificate
					String fingerprintString="";
					for(byte b : MessageDigest.getInstance("SHA1").digest(importDialog.certificate.getEncoded()))
					{
						if(Integer.toString(b&0xFF,16).length()==1)fingerprintString+="0";
						fingerprintString+=(Integer.toString(b&0xFF,16)); // maybe force to hex?
					}
					
					// add the new item into the tree
					new TreeItem(item,SWT.NONE).setText(importDialog.alias+": "+fingerprintString);
			
					idStore.store(new FileOutputStream(SeedConnector.idPath),SeedConnector.globalPass.toCharArray());
					friendsStore.store(new FileOutputStream(SeedConnector.friendsPath),SeedConnector.globalPass.toCharArray());
					serversStore.store(new FileOutputStream(SeedConnector.serversPath),SeedConnector.globalPass.toCharArray());
					
					keyTree.layout();
				}
				catch(Exception e1)
				{
					e1.printStackTrace();
				}
				
				// save all the keystores
			}
		});
		
		MenuItem removeKey=new MenuItem(menu,SWT.PUSH);
		removeKey.setText("remove key");
		removeKey.addSelectionListener(new SelectionListener()
		{
			public void widgetDefaultSelected(SelectionEvent e)
			{
			}

			public void widgetSelected(SelectionEvent e)
			{
				try
				{
					System.out.println(e);
				
					TreeItem item=keyTree.getSelection()[0];
					if(item==null)return;
					TreeItem parent=item.getParentItem();
					if(parent==null)return;
					
					KeyStore store=null; // which keystore to look in?
					if(parent.getText().equals("identities"))store=idStore;
					if(parent.getText().equals("friends"))store=friendsStore;
					if(parent.getText().equals("servers"))store=serversStore;
					System.out.println(parent.getText());
					
					String alias=null; // alias of the certificate in the keystore
					alias=item.getText().split(":")[0]; // split the string at the colon
					System.out.println(alias);
					
					if(store.containsAlias(alias))
					{
						store.deleteEntry(alias); // delete the entry from the keystore
						item.dispose();  // delete the entry from the tree
					}

					// save all the keystores
					idStore.store(new FileOutputStream(SeedConnector.idPath),SeedConnector.globalPass.toCharArray());
					friendsStore.store(new FileOutputStream(SeedConnector.friendsPath),SeedConnector.globalPass.toCharArray());
					serversStore.store(new FileOutputStream(SeedConnector.serversPath),SeedConnector.globalPass.toCharArray());
				}
				catch (Exception e1)
				{
					return;
				}
			}
		});	

		keyTree.setMenu(menu);
	}
}
